﻿using System;
using System.Collections.Generic;
using System.Text;
using Mighty.Common;
using System.Collections;

namespace Mighty.Brain
{
    /// <summary>
    /// 기본Brain. 모든 Brain의 기본이 되는 Brain이다. 모든 Brain은 이 클래스를 상속받아야만n 한다.
    /// 게임에 관련된 모든 정보를 가지고 있는 gameInfo 속성과 게임으로부터 호출되는 15개의 함수(이벤트)로 구성되어 있다.
    /// 게임으로부터 호출되는 15개의 함수는 다음과 같다.
    /// 
    ///        GameStartEvent,             // (모두) 게임시작
    ///        BettingReadyEvent,          // (모두) 베팅시작, 카드를 이미 나누어 주었다
    ///        BettingTicEvent,            // (개인) 베팅차례
    ///        BettingTalkEvent,           // (모두) 다른사람의 베팅 정보
    ///        BettingCompleteEvent,       // (모두) 베팅완료, 주공이 정해졌다
    ///        ChoiceCardEvent,            // (주공) 카드선택, 13장의 카드중 10장의 카드선택
    ///        LastBettingEvent,           // (주공) 최종베팅정보, 기루다무늬변경가능
    ///        LastBettingTalkEvent,       // (모두) 주공의 최종베팅정보
    ///        ChoiceFriendEvent,          // (주공) 프랜드선택
    ///        ChoiceFriendTalkEvent,      // (모두) 주공의 프랜드 정보
    ///        RoundReadyEvent,            // (모두) 각라운드의시작
    ///        RoundTicEvent,              // (각자) 카드낼차례
    ///        RoundCardThrowEvent,        // (모두) 다른사람의 카드 정보
    ///        RoundCompleteEvent,         // (모두) 각라운드의종료
    ///        GameEndEvent                // (모두) 게임의 종료
    /// </summary>
    public class LovelyBrain : BasicBrain
    {
        /// <summary>
        /// 베팅차례
        ///  * 지금까지 배팅된 정보(gameInfo.bettingHistory) 또는 마지막 pass가 아닌 베팅정보 gameInfo.betting를 참고하여 베팅을 결정한다
        /// </summary>
        /// <remarks>
        /// [기본행동] 베팅리밋(betting.limit)이 15이하 이면 베팅리밋을 +1하고 노기루다(Giruda.NoGiruda)로 베팅한다
        /// </remarks>
       

        /*  마이티, 조커, 기루다에이스

            *프랜드선택 
            -주공이 마이티(O)&&조커(O) -> 기루다에이스
            -주공이 마이티(O)&&조커(X) -> 조커
            -주공이 마이티(X)-> 마이티

            *베팅
            -Spade Heart Clover Diamond

            -베팅조건: 높은점수카드가 많을수록, 같은 무늬의 카드가 많을수록

            ***기루다무늬카드는 기본 5장이상일경우 베팅

            ***기루다에이스를 포함한 기루다 점수카드 4장 + 기루다제외 에이스 or 킹 있을 경우 -> 베팅: 16
            ***기루다에이스를 포함한 기루다 점수카드 3장 + 기루다제외 에이스 or 킹 있을 경우 -> 베팅: 15
            ***기루다에이스 없고 기루다점수카드  3장 -> 베팅: 14
            ***기루다 점수카드 1장이하 -> 패스

            ***위 상황에서 마이티 or 조커가 포함되어 있을 경우 -> 베팅 + 1 
         */

        public override Betting BettingTicEvent()
        {
            int Spadecnt = 0;
            int Clovercnt = 0;
            int Diamondcnt = 0;
            int Heartcnt = 0;

            int Spadepnt = 0;
            int Cloverpnt = 0;
            int Diamondpnt = 0;
            int Heartpnt = 0;
            int NoGirudapnt = 0;
                       
            int Jokercnt = 0;

            
            Betting betting = new Betting();
            
            /// 우선 카드 무늬별로 몇 장인지 체크 후 점수 카드 체크
            int[,] girudaCard = new int[4,15];
            int j = 0;                     

            while(j < gameInfo.myCards.Length)
            {
                if (gameInfo.myCards[j].shape == Shape.Spade) // girudaCard[0][] = Spade
                {                    
                    girudaCard[0,Spadecnt] = gameInfo.myCards[j].number;
                    Spadecnt++;
                    j++;
                }

                else if (gameInfo.myCards[j].shape == Shape.Clover) // girudaCard[1][] = Clover
                {
                    girudaCard[1,Clovercnt] = gameInfo.myCards[j].number;
                    Clovercnt++;
                    j++;                    
                }

                else if (gameInfo.myCards[j].shape == Shape.Diamond) // girudaCard[2][] = Diamond
                {
                    girudaCard[2,Diamondcnt] = gameInfo.myCards[j].number;
                    Diamondcnt++;
                    j++;                    
                }

                else if (gameInfo.myCards[j].shape == Shape.Heart) // girudaCard[3][] = Heart
                {
                    girudaCard[3,Heartcnt] = gameInfo.myCards[j].number;
                    Heartcnt++;
                    j++;                    
                }

                else if (gameInfo.myCards[j].shape == Shape.Joker)
                {
                    Jokercnt++;
                    j++;                    
                }
            }

            /// 베팅 조건: 기루다로 정하려는 무늬카드가 5장 이상일 때 베팅한다. 5장 미만일경우 패스한다.
            /// 그 조건을 만족하는지 확인하는 작업

            int maxCnt = 0;

            maxCnt = Spadecnt;
            
            if (maxCnt > Clovercnt)
            {                              
                if (maxCnt > Diamondcnt)
                {
                    if (maxCnt > Heartcnt)
                    {
                        maxCnt = Spadecnt;
                        betting.giruda = Giruda.Spade;
                    }
                    // max Heart
                    else
                    {
                        maxCnt = Heartcnt;
                        betting.giruda = Giruda.Heart;
                    }
                }
                // max Diamond
                else
                {
                    maxCnt = Diamondcnt;
                    if (maxCnt > Heartcnt)
                    {
                        maxCnt = Diamondcnt;
                        betting.giruda = Giruda.Diamond;
                    }

                    else
                    {
                        maxCnt = Heartcnt;
                        betting.giruda = Giruda.Heart;
                    }
                }
            }

            else
            {
                maxCnt = Clovercnt;
                // max Clover
                if (maxCnt > Diamondcnt)
                {
                    if (maxCnt > Heartcnt)
                    {
                        betting.giruda = Giruda.Clover;
                    }
                    else
                    {
                        maxCnt = Heartcnt;
                        betting.giruda = Giruda.Heart;
                    }
                }
                // max Diamond
                else
                {
                    maxCnt = Diamondcnt;
                    if (maxCnt > Heartcnt)
                    {
                        betting.giruda = Giruda.Diamond;
                    }
                    else
                    {
                        maxCnt = Heartcnt;
                        betting.giruda = Giruda.Heart;
                    }
                }
            } // 베팅할 기루다 무늬가 정해졌다.
            
            if (maxCnt < 5) // 기루다 무늬로 정할 카드가 5장 미만일 경우 패스
                betting.isPass = true;
            else
            {                
                if (maxCnt == Spadecnt) // 기루다 -> 스페이드
                {
                    for (int i = 0; i < Clovercnt; i++) // 기루다무늬 제외한 다른 무늬에서 에이스 or 킹이 있는지 확인
                    {
                        if (girudaCard[1, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Diamondcnt; i++)
                    {
                        if (girudaCard[2, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Heartcnt; i++)
                    {
                        if (girudaCard[3, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Spadecnt; i++) // 기루다무늬의 점수카드 확인
                    {
                        if (girudaCard[0, i] >= 10)
                            Spadepnt++;
                    }

                    if (Spadepnt <= 1) // 점수카드 1장이하 패스
                        betting.isPass = true;
                    else
                    {                           
                        for (int i = 0; i < Spadecnt; i++)
                        {
                            if (Spadepnt == 2 && (girudaCard[0, i] == 14) && (NoGirudapnt == 0)) // 점수카드 2장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 13;
                            }

                            else if (Spadepnt == 3 && (girudaCard[0, i] != 14) && (NoGirudapnt == 0)) // 점수카드 3장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 14;
                            }

                            else if (Spadepnt == 3 && (girudaCard[0, i] == 14) && (NoGirudapnt > 0)) // 점수카드 3장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 15;
                            }

                            else if (Spadepnt == 4 && (girudaCard[0, i] == 14) && (NoGirudapnt > 0)) // 점수카드 4장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 16;
                            }                           
                        }

                        for (int i = 0; i < Diamondcnt; i++) // 기루다 무늬가 스페이드인 경우 마이티는 다이아몬드 에이스이다. 마이티 -> 있다면 베팅 + 1
                        {
                            if (girudaCard[2, i] == 14)
                                betting.limit++;
                        }

                        if (Jokercnt > 0) // 조커 확인 -> 있다면 베팅 + 1
                            betting.limit++;
                        
                    }
                }

                else if (maxCnt == Clovercnt) // 기루다 -> 클로버
                {
                    NoGirudapnt = 0;
                    for (int i = 0; i < Spadecnt; i++) // 기루다무늬 제외한 다른 무늬에서 에이스 or 킹이 있는지 확인
                    {
                        if (girudaCard[0, i] == 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Diamondcnt; i++)
                    {
                        if (girudaCard[2, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Heartcnt; i++)
                    {
                        if (girudaCard[3, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Clovercnt; i++) // 기루다무늬의 점수카드 확인
                    {
                        if (girudaCard[1, i] >= 10)
                            Cloverpnt++;
                    }

                    if (Cloverpnt <= 1) // 점수카드 1장이하 패스
                        betting.isPass = true;
                    else
                    {
                        for (int i = 0; i < Clovercnt; i++)
                        {
                            if (Cloverpnt == 2 && (girudaCard[1, i] == 14) && (NoGirudapnt == 0)) // 점수카드 2장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 13;
                            }

                            else if (Cloverpnt == 3 && (girudaCard[1, i] != 14) && (NoGirudapnt == 0)) // 점수카드 3장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 14;
                            }

                            else if (Cloverpnt == 3 && (girudaCard[1, i] == 14) && (NoGirudapnt > 0)) // 점수카드 3장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 15;
                            }

                            else if (Cloverpnt == 4 && (girudaCard[1, i] == 14) && (NoGirudapnt > 0)) // 점수카드 4장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 16;
                            }
                        }

                        for (int i = 0; i < Spadecnt; i++) // 마이티 확인 -> 있다면 베팅 + 1
                        {
                            if (girudaCard[0, i] == 14)
                                betting.limit++;
                        }

                        if (Jokercnt > 0) // 조커 확인 -> 있다면 베팅 + 1
                            betting.limit++;
                    }
                }

                else if (maxCnt == Diamondcnt) // 기루다 -> 다이아몬드
                {
                    NoGirudapnt = 0;
                    for (int i = 0; i < Spadecnt; i++) // 기루다무늬 제외한 다른 무늬에서 에이스 or 킹이 있는지 확인
                    {
                        if (girudaCard[0, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Clovercnt; i++)
                    {
                        if (girudaCard[1, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Heartcnt; i++)
                    {
                        if (girudaCard[3, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Diamondcnt; i++) // 기루다무늬의 점수카드 확인
                    {
                        if (girudaCard[2, i] >= 10)
                            Diamondpnt++;
                    }

                    if (Diamondpnt <= 1) // 점수카드 1장이하 패스
                        betting.isPass = true;
                    else
                    {
                        for (int i = 0; i < Diamondcnt; i++)
                        {
                            if (Diamondpnt == 2 && (girudaCard[2, i] == 14) && (NoGirudapnt == 0)) // 점수카드 2장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 13;
                            }

                            else if (Diamondpnt == 3 && (girudaCard[2, i] != 14) && (NoGirudapnt == 0)) // 점수카드 3장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 14;
                            }

                            else if (Diamondpnt == 3 && (girudaCard[2, i] == 14) && (NoGirudapnt > 0)) // 점수카드 3장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 15;
                            }

                            else if (Diamondpnt == 4 && (girudaCard[2, i] == 14) && (NoGirudapnt > 0)) // 점수카드 4장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 16;
                            }
                        }

                        for (int i = 0; i < Spadecnt; i++) // 마이티 확인 -> 있다면 베팅 + 1
                        {
                            if (girudaCard[0, i] == 14)
                                betting.limit++;
                        }

                        if (Jokercnt > 0) // 조커 확인 -> 있다면 베팅 + 1
                            betting.limit++;
                    }
                }

                else if (maxCnt == Heartcnt) // 기루다 -> 하트
                {
                    NoGirudapnt = 0;
                    for (int i = 0; i < Spadecnt; i++) // 기루다무늬 제외한 다른 무늬에서 에이스 or 킹이 있는지 확인
                    {
                        if (girudaCard[0, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Clovercnt; i++)
                    {
                        if (girudaCard[1, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Diamondcnt; i++)
                    {
                        if (girudaCard[2, i] >= 13)
                            NoGirudapnt++;
                    }

                    for (int i = 0; i < Heartcnt; i++) // 기루다무늬의 점수카드 확인
                    {
                        if (girudaCard[3, i] >= 10)
                            Heartpnt++;
                    }

                    if (Heartpnt <= 1) // 점수카드 1장이하 패스
                        betting.isPass = true;
                    else
                    {
                        for (int i = 0; i < Heartcnt; i++)
                        {
                            if (Heartpnt == 2 && (girudaCard[3, i] == 14) && (NoGirudapnt == 0)) // 점수카드 2장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 13;
                            }

                            else if (Heartpnt == 3 && (girudaCard[3, i] != 14) && (NoGirudapnt == 0)) // 점수카드 3장이고 에이스가 없을때
                            {
                                betting.isPass = false;
                                betting.limit = 14;
                            }

                            else if (Heartpnt == 3 && (girudaCard[3, i] == 14) && (NoGirudapnt > 0)) // 점수카드 3장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 15;
                            }

                            else if (Heartpnt == 4 && (girudaCard[3, i] == 14) && (NoGirudapnt > 0)) // 점수카드 4장이고 에이스 잇고 기루다제외한 에이스 or 킹있을때
                            {
                                betting.isPass = false;
                                betting.limit = 16;
                            }
                        }

                        for (int i = 0; i < Spadecnt; i++) // 마이티 확인 -> 있다면 베팅 + 1
                        {
                            if (girudaCard[0, i] == 14)
                                betting.limit++;
                        }

                        if (Jokercnt > 0) // 조커 확인 -> 있다면 베팅 + 1
                            betting.limit++;
                    }
                }
            }

            return betting;
        }

        /*
            ***프랜드 선택하기
            ***주공이 마이티(O)&&조커(O) -> 기루다에이스
            ***주공이 마이티(O)&&조커(X) -> 조커
            ***주공이 마이티(X)-> 마이티
         */

        public override FriendPlayer ChoiceFriendEvent()
        {
            HandedCard[] MyCard = new HandedCard[10];
            FriendPlayer friend = new FriendPlayer();
            Card card = new Card();
            card.shape = Shape.Joker;

            for (int i = 0; i < 10; i++)
            {
                if (gameInfo.myCards[i] != gameInfo.mighty)         // 마이티 프랜드 ( 주공이 마이티 없을 경우 )
                {
                    friend.howToSelect = FriendPlayer.HowToSelect.card;
                    friend.cardCondition = gameInfo.mighty;
                    break;
                }

                else
                {
                    for (int j = 0; j < 10; j++)
                    {
                        if (gameInfo.myCards[j].shape == Shape.Joker)   // 기루다 에이스 프랜드 ( 주공이 마이티와 조커 모두 있을 경우 )
                        {
                            int Spadecnt = 0;
                            int Clovercnt = 0;
                            int Diamondcnt = 0;
                            int Heartcnt = 0;

                            while (j < gameInfo.myCards.Length) // 기루다 에이스를 찾기위해서 베팅에서 했던 과정을 여기서 다시 반복했다. 다른 방법을 찾지 못해서 이렇게 했다.ㅠㅠ
                            {
                                if (gameInfo.myCards[j].shape == Shape.Spade) // girudaCard[0][] = Spade
                                {
                                    Spadecnt++;
                                    j++;
                                }

                                else if (gameInfo.myCards[j].shape == Shape.Clover) // girudaCard[1][] = Clover
                                {
                                    Clovercnt++;
                                    j++;
                                }

                                else if (gameInfo.myCards[j].shape == Shape.Diamond) // girudaCard[2][] = Diamond
                                {
                                    Diamondcnt++;
                                    j++;
                                }

                                else if (gameInfo.myCards[j].shape == Shape.Heart) // girudaCard[3][] = Heart
                                {
                                    Heartcnt++;
                                    j++;
                                }
                            }

                            int maxCnt = 0;

                            

                            maxCnt = Spadecnt;

                            if (maxCnt > Clovercnt)
                            {
                                if (maxCnt > Diamondcnt)
                                {
                                    if (maxCnt > Heartcnt)
                                    {
                                        maxCnt = Spadecnt;
                                    }
                                    // max Heart
                                    else
                                    {
                                        maxCnt = Heartcnt;                                        
                                    }
                                }
                                // max Diamond
                                else
                                {
                                    maxCnt = Diamondcnt;
                                    if (maxCnt > Heartcnt)
                                    {
                                        maxCnt = Diamondcnt;
                                    }

                                    else
                                    {
                                        maxCnt = Heartcnt;
                                    }
                                }
                            }

                            else
                            {
                                maxCnt = Clovercnt;
                                // max Clover
                                if (maxCnt > Diamondcnt)
                                {
                                    if (maxCnt > Heartcnt)
                                    {
                                        maxCnt = Clovercnt;
                                    }
                                    else
                                    {
                                        maxCnt = Heartcnt;
                                    }
                                }
                                // max Diamond
                                else
                                {
                                    maxCnt = Diamondcnt;
                                    if (maxCnt > Heartcnt)
                                    {
                                        maxCnt = Diamondcnt;
                                    }
                                    else
                                    {
                                        maxCnt = Heartcnt;
                                    }
                                }
                            }

                            if (maxCnt == Spadecnt)
                            {
                                friend.howToSelect = FriendPlayer.HowToSelect.card;
                                friend.cardCondition.shape = Shape.Spade;
                                friend.cardCondition.number = 14;
                                break;
                            }

                            else if (maxCnt == Clovercnt)
                            {
                                friend.howToSelect = FriendPlayer.HowToSelect.card;
                                friend.cardCondition.shape = Shape.Clover;
                                friend.cardCondition.number = 14;
                                break;
                            }

                            else if (maxCnt == Diamondcnt)
                            {
                                friend.howToSelect = FriendPlayer.HowToSelect.card;
                                friend.cardCondition.shape = Shape.Diamond;
                                friend.cardCondition.number = 14;
                                break;
                            }

                            else if (maxCnt == Heartcnt)
                            {
                                friend.howToSelect = FriendPlayer.HowToSelect.card;
                                friend.cardCondition.shape = Shape.Heart;
                                friend.cardCondition.number = 14;
                                break;
                            }
                        }

                        else                                            // 조커 프랜드 ( 주공이 마이티는 있고 조커는 없을 경우 )
                        {
                            friend.howToSelect = FriendPlayer.HowToSelect.card;
                            friend.cardCondition.shape = Shape.Joker;
                            break;
                        }
                    }
                }                
            }

            return friend;
        }



        /// <summary>
        /// (주공)카드선택, 13장의 카드중 10장의 카드선택. 버릴3장의 카드에 cmdRemove=true로 설정해주어야 한다
        /// 만약 정확히 3장의 카드가 선택되지 않았을 경우에는 새로추가된 3장의 카드가 그대로 버려진다.
        /// ChoiceCardEvent 가 호출된 후에는 선택된 10장의 카드는 myCards[0]부터 차례대로 배치되고 버려진 3장의 카드는
        /// myCards[10]에서부터 배치되어 나중에 어떤 카드가 버려졌는지 알수 있게 해준다
        /// </summary>
        /// <remarks>
        /// [기본행동] 추가된 3장의 카드를 그대로 버린다
        /// </remarks>
        public override HandedCard[] ChoiceCardEvent()
        {
            for (int i = 0; i <= 9; i++)
            {
                gameInfo.myCards[i].cmdRemove = false;
            }
            for (int i = 10; i <= 12; i++)
            {
                gameInfo.myCards[i].cmdRemove = true;
            }
            return gameInfo.myCards;
        }

        /// <summary>
        /// 카드낼차례
        ///  * 각 사용자의 턴에 한번씩 호출되며 낼 카드를 결과값으로 리턴해야 한다. 
        ///  * 사용가능한 카드에는 myCards[i].isPossible 속성이 true로 설정되어 있다. 
        ///  * 만약 사용불가능한 카드를 낼 경우에 시스템은 카드배열에서 제일 처음 만나는 사용가능한 카드를 골라서 사용한다
        /// </summary>
        /// <remarks>
        /// [기본행동] 가능한 카드중에서 랜덤하게 하나의 카드를 선택한다
        /// </remarks>
        public override HandedCard RoundTicEvent()
        {
            ArrayList possibleCards = new ArrayList();
            foreach (HandedCard card in gameInfo.myCards)
            {
                if (card.isPossible) possibleCards.Add(card);
            }

            Random r = new Random();
            int k = r.Next(possibleCards.Count);

            return (HandedCard)possibleCards[k];
        }
    }
}

